#include<linux/module.h>
#include<linux/netdevice.h>
#include<linux/ethtool.h>
#include<linux/mutex.h>
#include<linux/list.h>
#include<linux/rculist.h>
#include<linux/spinlock.h>
#include<linux/pci.h>
#include<net/dcbnl.h>
#include<net/ipv6.h>
#include<net/addrconf.h>
#include<linux/if_ether.h>
#include<rdma/ib_verbs.h>
#include<rdma/ib_user_verbs.h>
#include<rdma/ib_umem.h>
#include<rdma/ib_addr.h>
#include<linux/printk.h>

#include "visre.h"
#include "visre_verbs.h"

MODULE_AUTHOR("xujia.Tan@viscore.com");
MODULE_DESCRIPTION("VisCore Driver");
MODULE_LICENSE("Dual BSD/GPL");

static int vis_net_add(struct net_device *ndev)
{
    int err;
    struct vis_re *vis = NULL;

    vis = ib_alloc_device(vis_re, ibdev);
    if(!vis)
        return -ENOMEM;

    vis->ndev = ndev;

    err = vis_register_device(vis);
    if(err) {
        ib_dealloc_device(&vis->ibdev);
        return err;
    }
    return 0;
}

static int vis_re_netdev_event(struct notifier_block *notifier,
        unsigned long event, void *ptr)
{
    struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
    struct vis_re *vis = NULL;
    int err = 0;

    if(is_vlan_dev(ndev)) 
        return -1;

    vis = vis_get_dev_from_net(ndev);
    if(!vis && event != NETDEV_REGISTER)
        return -1;

    if(strcmp(ndev->name, "ens33"))
        return -1;

    switch(event) {
        case NETDEV_REGISTER:
            if(vis)
                break;
            printk("ndev->name = %s, event = %ld\n", ndev->name, event);
            err = vis_net_add(ndev);
            if (err) {
                pr_err("failed to add %s\n", ndev->name);
                return -1;
            }
            break;
        case NETDEV_UNREGISTER:
            //ib_unregister_device_queued(&vis->ibdev);
            break;
        default:
            break;
    }
    return NOTIFY_DONE;
}

static struct notifier_block vis_re_netdev_notifier = {
    .notifier_call = vis_re_netdev_event
};

static int __init vis_re_mod_init(void)
{
    int rc = 0;
    printk("vis_re_mod_init\n");
    rc = register_netdevice_notifier(&vis_re_netdev_notifier);
    if (rc) {
        pr_err("%s: Cannot register to netdevice_notifier", ROCE_DRV_MODULE_NAME);
    }
    return rc;
}

static void __exit vis_re_mod_exit(void)
{
    printk("vis_re_mod_exit\n");
    //ib_unregister_driver(RDMA_DRIVER_RXE);
    //unregister_netdevice_notifier(&vis_re_netdev_notifier);
}

module_init(vis_re_mod_init);
module_exit(vis_re_mod_exit);
